﻿// реализация хождения юнита по карте с возможностью нахождения кратчайшего пути по волновому алгоритму
// матрица с элементами карты: 0 - вода, 1 -  земля, 2 - болото
var map = Array(
[1,2,0,1,1,2,2,0,2,0,1,1,0,0,2,0], [1,1,1,1,1,0,0,2,2,2,0,1,1,0,0,0],
[1,0,1,0,1,1,1,1,0,0,0,0,2,2,2,0], [0,0,1,0,0,0,2,2,0,0,0,0,0,0,1,0],
[1,1,1,1,0,2,2,2,0,2,0,0,1,1,1,1], [1,0,1,0,2,2,2,0,2,2,1,1,0,1,0,2],
[1,1,1,0,0,1,1,1,0,1,1,1,1,0,2,2], [1,2,0,0,1,1,0,0,1,1,0,0,1,1,0,0],
[1,2,2,0,0,1,0,0,1,0,0,0,1,2,0,0], [0,0,1,0,1,0,1,1,1,1,1,0,1,2,0,1],
[0,0,1,1,0,1,0,1,0,0,1,1,0,0,2,1], [2,2,2,2,0,0,1,1,0,0,2,2,0,2,2,0],
[0,2,0,0,2,0,0,1,1,2,0,0,0,2,2,0], [0,0,0,0,0,2,1,1,0,2,0,0,0,0,1,1],
[1,2,2,2,0,0,1,0,0,0,1,1,1,0,0,2], [1,0,1,1,1,1,1,0,1,1,0,1,2,2,0,2]);
// матрица с элементом карты - стена
var obj_map = Array(
[0,0,1,0,0,0,0,1,0,1,0,0,1,1,0,0], [0,0,0,0,0,1,1,0,0,0,1,0,0,1,1,0],
[0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0], [1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1],
[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], [0,1,0,1,0,0,0,1,0,0,0,0,1,0,1,0],
[0,0,0,1,1,0,0,0,1,0,0,0,0,1,0,0], [0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0], [0,1,0,1,0,1,0,0,0,0,0,1,0,0,1,0],
[0,1,0,0,1,0,1,0,0,0,0,0,1,1,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1], [1,1,0,1,1,0,0,0,1,0,1,1,0,0,0,0],
[0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0], [0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0]);
var obj = Array("стена.png");   // массив ресурсов полей, по кот. нельзя ходить
var elem_map = Array("вода.png","земля.png","болото.png");  // массив ресурсов матрицы 1
var gamer = Array("игрок.png"); // массив ресурсов игроков
var gamer_img = new Array();    // массив изображений игроков
var elem_img = new Array();     // массив изображений элементов карты матрицы 1
var obj_img = new Array();      // массив изображений объектов карты матрицы 2
var loaded = 0;     // индикатор загрузки ресурсов
var load_time;
var y_mouse;    // координата y мыши
var x_mouse;    // координата x мыши
var x_mouse_save, y_mouse_save; // для хранения конечной точки перемещения
var x_map = 375;
var y_map = 0;
var x_player = 0;   // координата X фигуры
var y_player = 0;   // координата Y фигуры
var x_save, y_save; // координаты для сохранения позиции фигуры
var finish_dote = false;    // индикатор существования конечной точки
var way_found = false;      // индикатор, что путь найден
var arc11 = 0, arc12 = 0, arc21 = 0, arc22 = 0, arc31 = 0, arc32 = 0;
var focus = true;
var x = 0, y = 0;
var N = map.length + 2, M = map[0].length + 2;  // N, M - размер матрицы ходов
var matrix = new Array(N);  // матрица ходов
var movement;   // массив движения; 0 - вправо; 1 - влево; 2 - вниз; 3 - вверх

function load_Image() {
    // загрузка изображений
    for (var i = 0; i < elem_map.length; i++) {
        elem_img[i] = new Image();
        elem_img[i].src = elem_map[i];
        elem_img[i].onload = function () {
            loaded++;
        }
    }
    for (var j = 0; j < gamer.length; j++) {
        gamer_img[j] = new Image();
        gamer_img[j].src = gamer[j];
        gamer_img[j].onload = function () {
            loaded++;
        }
    }
    for (var r = 0; r < obj.length; r++) {
        obj_img[r] = new Image();
        obj_img[r].src = obj[r];
        obj_img[r].onload = function () {
            loaded++;
        }
    }
}

function load_All() {
    // проверка загрузки ресурсов
    if (loaded == elem_map.length + gamer.length + obj.length) {
        clearInterval(load_time);
        load_time = setInterval(game_Update, 50);
        setInterval(DrawElips, 40);
    }
}


function game_Update() {
    // обновление карты
    ctx.clearRect(0, 0, 800, 400);
    draw_Game();
}


function mouse_Move(e) {
    // обработчик перемещения курсора мыши
    x = e.pageX;
    y = e.pageY;
    y_mouse = (2 * (y - canvas.offsetTop - y_map) - x + canvas.offsetLeft + x_map) / 2;
    x_mouse = x + y_mouse - x_map - 25 - canvas.offsetLeft;
    y_mouse = Math.round(y_mouse / 25);
    x_mouse = Math.round(x_mouse / 25);
    // x_mouse, y_mouse - координаты точек над кот. курсор мыши
    document.title = "tileY:" + y_mouse + " | tileX:" + x_mouse;
}


function draw_Game() {
    // перерисовка карты
    var gamer_height = 25;
    var gamer_width = 50;
    for (var i = 0; i < map.length; i++) {
        for (var j = 0; j < map[i].length; j++) {
            var draw_cell = map[i][j];
            var draw_wall = obj_map[i][j];
            var x_pos = (i - j) * gamer_height + x_map;
            var y_pos = (i + j) * gamer_height / 2 + y_map;
            // прорисовка клетки карты
            ctx.drawImage(elem_img[draw_cell], x_pos, y_pos);
            if (draw_wall) {
                // прорисовка стены
                ctx.drawImage(obj_img[draw_wall - 1], x_pos, y_pos - (obj_img[draw_wall - 1].height / 2));
            }
            if (i == x_player && j == y_player) {
                // прорисовка фигуры игрока
                x_save = x_pos/4;   // сохранение позиций игрока
                y_save = y_pos;
                ctx.drawImage(gamer_img[0], x_pos, y_pos - (gamer_img[0].height / 2) - 13);
            }
            if (i == x_mouse && j == y_mouse) {
                // засветление клетки на месте установки курсора мыши
                if (!draw_wall)
                    ctx.fillStyle = 'rgba(255, 255, 120, 0.7)';
                else
                    ctx.fillStyle = 'rgba(152, 120, 237, 0.7)';
                ctx.beginPath();
                ctx.moveTo(x_pos, y_pos + 12.5);
                ctx.lineTo(x_pos + 25, y_pos);
                ctx.lineTo(x_pos + 50, y_pos + 12.5);
                ctx.lineTo(x_pos + 25, y_pos + 25);
                ctx.fill();
            }
        }
    }
    if (finish_dote) {
        // прорисовка финишной точки
        var x_ps_1 = (x_mouse_save - y_mouse_save) * gamer_height + x_map;
        var y_ps_1 = (x_mouse_save + y_mouse_save) * gamer_height / 2 + y_map;
        ctx.fillStyle = 'rgba(255, 0, 0, 0.7)';
        ctx.beginPath();
        ctx.moveTo(x_ps_1, y_ps_1 + 12.5);
        ctx.lineTo(x_ps_1 + 25, y_ps_1);
        ctx.lineTo(x_ps_1 + 50, y_ps_1 + 12.5);
        ctx.lineTo(x_ps_1 + 25, y_ps_1 + 25);
        ctx.fill();
    }
    if (way_found) {
    // прорисовка пути следования
        var x = x_player, y = y_player;
        ctx.fillStyle = 'rgba(51, 120, 203, 0.7)';
        for (var r = 0; r < movement.length - 1; r++) {
            if (!movement[r]) { x += 1;}
            else if (movement[r] == 1) { x -= 1;}
            else if (movement[r] == 2) { y += 1;}
            else if (movement[r] == 3) { y -= 1;}
            var x_ps = (x - y) * gamer_height + x_map;
            var y_ps = (x + y) * gamer_height / 2 + y_map;
            ctx.beginPath();
            ctx.moveTo(x_ps, y_ps + 12.5);
            ctx.lineTo(x_ps + 25, y_ps);
            ctx.lineTo(x_ps + 50, y_ps + 12.5);
            ctx.lineTo(x_ps + 25, y_ps + 25);
            ctx.fill();
        }
    }
    if(focus) {
        // если игрок находится в фокусе - прорисовка элипса активности у основания фигуры игрока
        ctx.save();
        ctx.strokeStyle = "rgba(217, 220, 95, 0.5)";
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.scale(4, 1);
        ctx.arc(x_save + 6.25, y_save + 12.5, 6.25, 0, Math.PI * 2, true);
        ctx.stroke();
        ctx.restore();
    }
}



function Key_code(event) {
    // обработчик нажатия клавиш управления, реализующих движение фигуры игрока на карте
    var keyCode;
    if(focus) {
    if (event == null) {
        keyCode = window.event.keyCode;
    }
    else {
        keyCode = event.keyCode;
    }
    document.title = keyCode;
    switch (keyCode) {
        case 38:
            if (!obj_map[x_player - 1][y_player]) {
                x_player--;
            }
            break;
        case 40:
            if (!obj_map[x_player + 1][y_player]) {
                x_player++;
            }
            break;
        case 39:
            if (!obj_map[x_player][y_player - 1] && y_player > 0) {
                y_player--;
            }
            break;
        case 37:
            if (!obj_map[x_player][y_player + 1] && y_player < obj_map[0].length - 1) {
                y_player++;
            }
            break;
        default:
            break;
    }
    }
}


function mouseDoubleDown(evt) {
    if (!obj_map[x_mouse][y_mouse]) {
        initMatrix();   // инициализация матрицы
        x_mouse_save = x_mouse;
        y_mouse_save = y_mouse;
        finish_dote = true;
        var i, j;
        matrix[x_mouse_save+1][y_mouse_save+1] = 0;
        matrix[x_player+1][y_player+1] = 253;
        var Ni = 0, Nk = 256, ind = 0;
        while(Ni < Nk) {
            for (i = 1; i < N - 1; i++) {
                for (j = 1; j < M - 1; j++) {
                    if (matrix[i][j] == Ni) {
                        if (matrix[i+1][j] == 253) { ind = 1; break;}
                        if (matrix[i+1][j] == 254) { matrix[i+1][j] = Ni + 1;}
                        if (matrix[i-1][j] == 253) { ind = 1; break;}
                        if (matrix[i-1][j] == 254) { matrix[i-1][j] = Ni + 1;}
                        if (matrix[i][j+1] == 253) { ind = 1; break;}
                        if (matrix[i][j+1] == 254) { matrix[i][j+1] = Ni + 1;}
                        if (matrix[i][j-1] == 253) { ind = 1; break;}
                        if (matrix[i][j-1] == 254) { matrix[i][j-1] = Ni + 1;}

                    }
                }
            }
            Ni++;
            if (ind) {
                break;
            }
        }
        if (Ni == Nk-1) { var s = "Pyt ne naiden!"; way_found = false;}
        else if (Ni != Nk-1) {
            movement = new Array(Ni);
            var x1 = x_player + 1, y1 = y_player + 1, min = 254, x2, y2;
            for (i = 0; i < Ni; i++) {
                if (matrix[x1][y1] == 0) { break;}
                if (matrix[x1+1][y1] < min) { min = matrix[x1+1][y1]; x2 = x1+1; y2 = y1; movement[i] = 0;}
                if (matrix[x1-1][y1] < min) { min = matrix[x1-1][y1]; x2 = x1-1; y2 = y1; movement[i] = 1;}
                if (matrix[x1][y1+1] < min) { min = matrix[x1][y1+1]; x2 = x1; y2 = y1+1; movement[i] = 2;}
                if (matrix[x1][y1-1] < min) { min = matrix[x1][y1-1]; x2 = x1; y2 = y1-1; movement[i] = 3;}
                x1 = x2; //x_player = x1 - 1;
                y1 = y2; //y_player = y1 - 1;
            }
            way_found = true;
        }
        focus = true;
    }
}


function mouseDown(evt) {
    // обработчик нажатия клавиши мыши
    if(x_player != x_mouse || y_player != y_mouse) {
        // снятие фокуса с фигуры игрока
        focus = false;
    }
    else if(x_player == x_mouse && y_player == y_mouse) {
        // установка фокуса с фигуры игрока
        focus = true;
    }
}


function DrawElips() {
    // прорисовка элипса фокуса активности фигуры игрока
    if(focus) {
        if(arc11 >= 360) {
            arc11 = 0;
        }
        arc12 = arc11 + 90;
        ctx.save();
        ctx.strokeStyle = "rgba(255, 0, 0, 1)";
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.scale(4, 1);
        ctx.arc(x_save + 6.25, y_save + 12.5, 6.25, (arc11 * Math.PI)/180, (arc12 * Math.PI)/180, false);
        ctx.stroke();
        ctx.restore();
        arc11 += 30;
    }
}


function initMatrix() {
    // инициализация матрицы поиска
    for (var i = 0; i < N - 2; i++) {
        for (var j = 0; j < M - 2; j++) {
            if (obj_map[i][j]) {
                matrix[i+1][j+1] = 255;
            } else if (!obj_map[i][j]) {
                matrix[i+1][j+1] = 254;
            }
        }
    }
}


function goTo() {
    if (way_found) {
        finish_dote = false;
        way_found = false;
        x_player = x_mouse_save;
        y_player = y_mouse_save;
        focus = true;
    }
}


function init(){
	document.onkeydown = Key_code;  // обработчик нажатия на клавиши
	canvas = document.getElementById("canvas_1");
	ctx = canvas.getContext("2d");	    
	load_Image();   // загрузка изображений
	load_time = setInterval(load_All, 100);
	canvas.addEventListener("mousemove", mouse_Move, false);   // обработчик перемещения курсора мыши
    canvas.ondblclick = mouseDoubleDown;    // присвоения обработчика двойного клика
    canvas.onmousedown = mouseDown;     // присвоение обработчика нажатия клавиши мыши
    for (var i = 0; i < N; i++) {
        matrix[i] = new Array(M);
    }
    for (var r = 0; r < N; r++) {
        matrix[r][0] = 255;
        matrix[r][M-1] = 255;
    }
    for (var j = 0; j < M; j++) {
        matrix[0][j] = 255;
        matrix[N-1][j] = 255;
    }
}